#include "files.h"


static FILE * inFile;
static FILE * outFile;

static unsigned char buffer_in,buffer_out;

static int edf;

static char nb_bit_in,nb_bit_out; //respectivement, le nombre de bit utile dans les buffers

void test_eof_inFile() {
  int lu;
  lu = getc (inFile);
  
  printf("test eof lu= %d \n",lu);
  
  if (lu != EOF)
    {
      ungetc (lu, inFile);
      edf = 0;;
    }
  else
    edf = 1;
}
int eof_in() {
    return edf && (nb_bit_in==0);
}

FILE * open_in(const char * nomfichier) {
    inFile = fopen (nomfichier,"r");
    if (inFile == NULL)
    {
      fprintf (stderr, "Echec de l'ouverture de fichier en lecture\n");
      exit (EXIT_FAILURE);
    }
    buffer_in = 0;
    nb_bit_in = 0;
    return inFile;
}


FILE * open_out(const char * nomfichier) {
    outFile = fopen (nomfichier,"w+");
    if (outFile == NULL)
    {
      fprintf (stderr, "Echec de l'ouverture de fichier en ecriture\n");
      exit (EXIT_FAILURE);
    }
    buffer_out = 0;
    nb_bit_out = 0;
    return outFile;
}
void close_out() {
    int nbecris;
    if (nb_bit_out>0) {
        buffer_out = buffer_out << (8 - nb_bit_out);
        nbecris=  fprintf(outFile,"%c",buffer_out);
        printf("nbecris = %d et code ecris = %X\n",nbecris,buffer_out);
    }
    fclose(outFile);
    printf("Fichier de sortie ferme\n");
    
}

Code getCode(char nbBit) {
    Code res = 0;
    unsigned char mask;
    int nblu;
    unsigned char tmp_buffer;
    
    if (nbBit<1)
    { 
      fprintf (stderr, "On ne peut pas lire moins d'un bit\n");
      exit (EXIT_FAILURE);
    }
    
    while(nbBit>0) {
        //on rempli le buffer si vide
        if (nb_bit_in==0) {
            nblu = fscanf(inFile,"%c",&buffer_in);
           // test_eof_inFile();
            //printf("nblu = %d et bits lu = %X\n",nblu,buffer_in);
            nb_bit_in = 8;
        } else if (nb_bit_in < 0) {
            fprintf (stderr, "nb bit restant in negatif\n");
            exit (EXIT_FAILURE);
        }
        
        if (nb_bit_in>=nbBit) { //le buffer contient les bits recherché
            tmp_buffer = buffer_in >> (8 - nbBit ); //On deplace la partie du buffer recherché en poid faible
            //mask = 255 - (pow(2,nbBit) -1); //Tout à 1 sauf les nbBit de poid faible voulu
            //tmp_buffer = tmp_buffer & ~mask; //on recupere la partie du buffer recherché
            res = ( res << nbBit ) | tmp_buffer;
            buffer_in = buffer_in << nbBit;
            nb_bit_in = nb_bit_in - nbBit;
            nbBit = 0;
        } else { //buffer insuffisant, il faut recupérer tout puis lire
            tmp_buffer = buffer_in >> (8 - nb_bit_in );
            res = (res << nb_bit_in) | tmp_buffer;
            nbBit = nbBit - nb_bit_in;
            nb_bit_in = 0;
            buffer_in = 0 ;
        }
    }
    return res;
}


void putCode(Code code, char nbBit){
    int nbecris;
    unsigned char mask;
    unsigned char tmp;
    unsigned char place_restante;
    if (nbBit<1)
    { 
      fprintf (stderr, "On ne peut pas lire moins d'un bit\n");
      exit (EXIT_FAILURE);
    }
    
    while (nbBit>0) {
        if (nb_bit_out < 0) {
            fprintf (stderr, "nb bit restant out negatif\n");
            exit (EXIT_FAILURE);
        } else if (nb_bit_out >8) {
            fprintf (stderr, "nb bit restant out trop grand\n");
            exit (EXIT_FAILURE);
       } else  { // 0 <=nb_bit_out <=8 normalement jamais == 8 mais on sait jamais
            place_restante = 8 - nb_bit_out;
            //printf("buffer avant = %X ---",buffer_out);
            if ((place_restante <= nbBit)) { //si le buffer n'a plus assez de place
                tmp = code >> (nbBit - place_restante); // on decale en poids faible les bits recherché
                buffer_out = (buffer_out << place_restante ) | tmp; //on place ces bits en fin de buffer
                nb_bit_out =  8;
                nbBit = nbBit - place_restante;
                mask = pow(2,nbBit) -1;
                code = code & mask;
            } else { //si le buffer peut tout contenir
                buffer_out = (buffer_out << nbBit );
                buffer_out = buffer_out | code;
                nb_bit_out = nb_bit_out + nbBit;
                nbBit = 0 ;
            }
            //printf(" buffer apres = %X\n",buffer_out);
       }
        
        if (nb_bit_out==8) {
            nbecris=  fprintf(outFile,"%c",buffer_out);
            printf("nbecris = %d et bits ecris = %X\n",nbecris,buffer_out);
            nb_bit_out = 0;
            buffer_out = 0;
        } else if (nb_bit_out < 0) {
            fprintf (stderr, "nb bit restant out negatif 2\n");
            exit (EXIT_FAILURE);
        } else if (nb_bit_out >8) { 
            fprintf (stderr, "nb bit restant out trop grande 2\n");
            exit (EXIT_FAILURE);
        }
    }
}
